class_name Run
extends Node

const BATTLE_SCENE = preload("uid://cfexy6g2vwwl6")
const BATTLE_REWARD_SCENE = preload("uid://b52rtjpbc1764")
const CAMPFIRE_SCENE = preload("uid://wgmxiffp7rh2")
const SHOP_SCENE = preload("uid://cgnptwnbnsxha")
const TREASURE_SCENE = preload("uid://872rpyhu8kj5")
const WIN_SCREEN_SCENE = preload("uid://dlfwlt744bn1c")


@export var run_startup: RunStartup

@onready var current_view: Node = %CurrentView

@onready var deck_button: CardPileOpener = %DeckButton
@onready var deck_view: CardPileView = %DeckView
@onready var gold_ui: GoldUI = %GoldUI
@onready var map: Map = %Map
@onready var health_ui: HealthUI = %HealthUI
@onready var relic_handler: RelicHandler = %RelicHandler
@onready var relic_tooltip: RelicTooltip = %RelicTooltip
@onready var pause_menu: PauseMenu = %PauseMenu

var character: CharacterStats
var run_stats: RunStats
var save_data: SaveGame

func _ready() -> void:
	if not run_startup:
		return
	pause_menu.save_and_quit.connect(func():
		get_tree().change_scene_to_file(AutoLoader.MAIN_MENU_FILE)
	)
	match run_startup.type:
		RunStartup.Type.NEW_RUN:
			character = run_startup.character.create_instance()
			_start_run()
		RunStartup.Type.CONTINUE:
			_load_run()


func _save_run_data(was_on_map: bool) -> void:
	save_data.rng_seed = RNG.instance.seed
	save_data.rng_state = RNG.instance.state
	save_data.char_stats = character
	save_data.current_deck = character.deck
	save_data.current_health = character.health
	save_data.floors_climbed = map.floors_climbed
	save_data.last_room = map.last_room
	save_data.map_data = map.map_data
	save_data.relics = relic_handler.get_all_relics()
	save_data.run_stats = run_stats
	save_data.was_on_map = was_on_map
	save_data.save_data()


func _load_run() -> void:
	save_data = SaveGame.load_data()
	assert(save_data, "Couldn't load last save")
	RNG.set_from_save_data(save_data.rng_seed, save_data.rng_state)
	character = save_data.char_stats
	character.deck = save_data.current_deck
	character.health = save_data.current_health
	relic_handler.add_relics(save_data.relics)
	run_stats = save_data.run_stats
	map.load_map(save_data.map_data, save_data.floors_climbed, save_data.last_room)
	_setup_event_connections()
	_setup_top_bar()
	if save_data.last_room and not save_data.was_on_map:
		_on_map_exited(save_data.last_room)


func _start_run() -> void:
	run_stats = RunStats.new()
	_setup_event_connections()
	_setup_top_bar()
	map.generate_new_map()
	
	save_data = SaveGame.new()
	_save_run_data(true)
	
func _setup_top_bar() -> void:
	character.stats_changed.connect(health_ui.update_stats.bind(character))
	health_ui.update_stats(character)
	gold_ui.run_stats = run_stats
	deck_button.card_pile = character.deck
	deck_view.card_pile = character.deck
	deck_button.pressed.connect(deck_view.show_current_view.bind("Deck"))
	relic_handler.add_relic(character.starting_relic)
	Events.relic_tooltip_request.connect(relic_tooltip.show_tooltip)

func _setup_event_connections() -> void:
	Events.battle_won.connect(_on_battle_won)
	Events.battle_reward_exited.connect(_show_map)
	Events.campfire_exited.connect(_show_map)
	Events.shop_exited.connect(_show_map)
	Events.treasure_room_exited.connect(_on_treasure_room_exited)
	Events.map_exited.connect(_on_map_exited)


func _on_treasure_room_exited(relic: Relic) -> void:
	var reward_scene : BattleReward = _change_view(BATTLE_REWARD_SCENE)
	reward_scene.run_stats = run_stats
	reward_scene.character_stats = character
	reward_scene.relic_handler = relic_handler
	
	reward_scene.add_relic_reward(relic)


func _on_treasure_room_entered() -> void:
	var new_scene : Treasure = _change_view(TREASURE_SCENE)
	new_scene.char_stats = character
	new_scene.relic_handler = relic_handler
	new_scene.generate_relic()

func _on_map_exited(room: Room) -> void:
	_save_run_data(false)
	match room.type:
		Room.Type.MONSTER, Room.Type.BOSS:
			_on_battle_room_entered(room)
		Room.Type.TREASURE:
			_on_treasure_room_entered()
		Room.Type.CAMPFIRE:
			_on_campfire_entered()
		Room.Type.SHOP:
			_on_shop_entered()


func _on_shop_entered() -> void:
	var shop_scene : Shop = _change_view(SHOP_SCENE)
	shop_scene.char_stats = character
	shop_scene.run_stats = run_stats
	shop_scene.relic_handler = relic_handler
	Events.do_shop_entered(shop_scene)
	shop_scene.populate_shop()


func _change_view(scene: PackedScene) -> Node:
	if current_view.get_child_count() > 0:
		current_view.get_child(0).queue_free()
	get_tree().paused = false
	var new_scene = scene.instantiate()
	current_view.add_child(new_scene)
	map.hide_map()
	return new_scene
	
func _show_map() -> void:
	if current_view.get_child_count() > 0:
		current_view.get_child(0).queue_free()
	map.show_map()
	map.unlock_next_rooms()
	_save_run_data(true)
	
func _on_battle_won() -> void:
	if map.floors_climbed == MapGenerator.FLOORS:
		var win_screen : WinScreen = _change_view(WIN_SCREEN_SCENE)
		win_screen.character = character
		SaveGame.delete_data()
	else:
		var reward_scene :BattleReward = _change_view(BATTLE_REWARD_SCENE)
		reward_scene.run_stats = run_stats
		reward_scene.character_stats = character
		reward_scene.add_gold_reward(map.last_room.battle_stats.roll_gold_reward())
		reward_scene.add_card_reward()


func _on_battle_room_entered(room: Room) -> void:
	var battle_scene: Battle = _change_view(BATTLE_SCENE)
	battle_scene.char_stats = character
	battle_scene.battle_stats = room.battle_stats
	battle_scene.relics = relic_handler
	battle_scene.start_battle()


func _on_campfire_entered() -> void:
	var campfire_scene: Campfire = _change_view(CAMPFIRE_SCENE)
	campfire_scene.char_stats = character
